package com.github.prontera.service;

import java.math.BigDecimal;
import java.text.MessageFormat;
import java.time.OffsetDateTime;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.github.prontera.Shift;
import com.github.prontera.StatusCode;
import com.github.prontera.domain.Client;
import com.github.prontera.domain.ClientBankCard;
import com.github.prontera.domain.OrderRefund;
import com.github.prontera.domain.SysDict;
import com.github.prontera.domain.TalentOrder;
import com.github.prontera.domain.enums.ClientBankCardTypeEnum;
import com.github.prontera.domain.enums.ConsumeLevelTypeEnum;
import com.github.prontera.domain.enums.ConsumeSmallTypeEnum;
import com.github.prontera.domain.enums.ConsumeTypeEnum;
import com.github.prontera.domain.enums.OrderAcceptStatusEnum;
import com.github.prontera.domain.enums.OrderRefundStatusEnum;
import com.github.prontera.domain.enums.OrderStatusEnum;
import com.github.prontera.domain.enums.PayChannelEnum;
import com.github.prontera.domain.enums.PayStatusEnum;
import com.github.prontera.domain.enums.VipStatusEnum;
import com.github.prontera.domain.enums.VipTypeEnum;
import com.github.prontera.model.ConsumeMessageTemplate;
import com.github.prontera.persistence.CrudMapper;
import com.github.prontera.persistence.SysDictMapper;
import com.github.prontera.util.IdWorker;
import com.google.common.base.Preconditions;

/**
 * 退款管理
 */
@Service
public class OrderRefundService extends CrudServiceImpl<OrderRefund>{
    
	 @Autowired
	 private TalentOrderService talentOrderService;
	 @Autowired
	 private ConsumeService consumeService;
	 @Autowired
     private ClientService clientService;
     @Autowired
     private SysDictMapper sysDictMapper;
     @Autowired
     private ClientBankCardService clientBankCardService;
    
  	@Autowired
    public OrderRefundService(CrudMapper<OrderRefund> mapper) {
        super(mapper);
    }

	/**
   	 * 退款VIP
   	 */
   	@Transactional(propagation = Propagation.REQUIRED)
 	public boolean refundTalendOrder(TalentOrder order) {
   		talentOrderService.update(order);
   		if(order.getStatus()!=OrderStatusEnum.REFUNDS){
 			Shift.fatal(StatusCode.USER_NOT_EXISTS, "该笔订单暂时未申请退款请稍后再试,无法退款");
 		}
 		TalentOrder talentOrder=talentOrderService.get(order.getId());
 		if(talentOrder==null){
 			Shift.fatal(StatusCode.USER_NOT_EXISTS, "订单不存在");
 		}
 		ClientBankCard findClientBankCard=new ClientBankCard();
 		findClientBankCard.setCardType(ClientBankCardTypeEnum.getEnumByCode(talentOrder.getPayChannel().getCode()));
 		findClientBankCard.setClientId(talentOrder.getClientId());
 		ClientBankCard clientBankCard=clientBankCardService.findOne(findClientBankCard);
 		
 		if(clientBankCard==null){
 			Shift.fatal(StatusCode.INVALID_PARAMS_CONVERSION, "请先绑定支付方式");
 		}
 		
 		OrderRefund refund=new OrderRefund();
 		refund.setReason("用户申请退单");
 		refund.setAmount(talentOrder.getAmount());
 		refund.setClientId(talentOrder.getClientId());
 		refund.setType(VipTypeEnum.TALEND_ORDER);
 		refund.setPayChannel(talentOrder.getPayChannel());
 		refund.setTradeNo(talentOrder.getTradeNo()); 		
 		refund.setBankCardId(clientBankCard.getId());
 		insert(refund);
 		return Boolean.TRUE;
 	}
  	
   	/**
   	 * 退款VIP
   	 */
   	@Transactional(propagation = Propagation.REQUIRED)
 	public boolean refundVip(Long clientId,PayChannelEnum payChannel) {
 		Client client=clientService.get(clientId);
 		if(client==null){
 			Shift.fatal(StatusCode.USER_NOT_EXISTS, "用户不存在");
 		}
 		if(client.getVipStatus()!=VipStatusEnum.VIP){
 			Shift.fatal(StatusCode.USER_NOT_EXISTS, "该用户暂时不是VIP,无法退款");
 		}
 		SysDict dict=sysDictMapper.get(client.getVipAmountId());
 		if(dict==null){
 			Shift.fatal(StatusCode.UNAVAILABLE_EXCEPTION, "缺少数据字典类型支持");
 		}
 		
 		ClientBankCard findClientBankCard=new ClientBankCard();
 		findClientBankCard.setCardType(ClientBankCardTypeEnum.getEnumByCode(payChannel.getCode()));
 		findClientBankCard.setClientId(clientId);
 		ClientBankCard clientBankCard=clientBankCardService.findOne(findClientBankCard);
 		
 		if(clientBankCard==null){
 			Shift.fatal(StatusCode.INVALID_PARAMS_CONVERSION, "请先绑定支付方式");
 		}
 		
 		OrderRefund refund=new OrderRefund();
 		refund.setAmount(dict.getValue());
 		refund.setClientId(clientId);
 		refund.setType(VipTypeEnum.VIP);
 		refund.setPayChannel(payChannel);
 		refund.setTradeNo(String.valueOf(new IdWorker().getId())); 		
 		refund.setBankCardId(clientBankCard.getId());
 		insert(refund);
 		
 		Client updateClient=new Client();
 		updateClient.setId(clientId);
 		updateClient.setVipStatus(VipStatusEnum.BACK_AMOUNT);
 		if(clientService.update(updateClient)<=0){
 			Shift.fatal(StatusCode.INVALID_PARAMS_CONVERSION, "参数错误");
 		}
 		return Boolean.TRUE;
 	}

   	/**
   	 * 提现--->可提现金额
   	 */
   	@Transactional(propagation = Propagation.REQUIRED)
 	public boolean refundDepositAmount(Long clientId,BigDecimal amount,PayChannelEnum payChannel) {
 		if(!clientService.updateLockedDepositAmount(clientId, amount.multiply(new BigDecimal(-1)))){
 			Shift.fatal(StatusCode.LESS_THAN_BALANCE, "可提现金额不足");
 		}
 		
 		ClientBankCard findClientBankCard=new ClientBankCard();
 		findClientBankCard.setCardType(ClientBankCardTypeEnum.getEnumByCode(payChannel.getCode()));
 		findClientBankCard.setClientId(clientId);
 		ClientBankCard clientBankCard=clientBankCardService.findOne(findClientBankCard);
 		
 		if(clientBankCard==null){
 			Shift.fatal(StatusCode.INVALID_PARAMS_CONVERSION, "请先绑定支付方式");
 		}
 		
 		OrderRefund refund=new OrderRefund();
 		refund.setAmount(amount);
 		refund.setPayChannel(payChannel);
 		refund.setClientId(clientId);
 		refund.setType(VipTypeEnum.DEPOSIT_AMOUNT);
 		refund.setTradeNo(String.valueOf(new IdWorker().getId()));
 		refund.setBankCardId(clientBankCard.getId());
 		insert(refund);
 		return Boolean.TRUE;
 	}
   	
   	@Transactional(propagation = Propagation.REQUIRED)
	public boolean refundOrder(OrderRefund orderRefund) {
  		//同意退款
  		if (orderRefund.getStatus()==OrderRefundStatusEnum.SUCCESS) {
  			Client client=new Client();
  			client.setId(orderRefund.getClientId());
  			if(orderRefund.getType()==VipTypeEnum.VIP){
  				client.setVipStatus(VipStatusEnum.BACK_AMOUNT);
  	  			client.setNullVipAmountId(true);
  	  			clientService.update(client);
  	  			//支出
  	  			consumeService.insertConsume(orderRefund.getClientId(),ConsumeSmallTypeEnum.REFUND_VIP, ConsumeMessageTemplate.MSG_REFUND_VIP,ConsumeLevelTypeEnum.DEPOSIT,null, null,ConsumeTypeEnum.OUTCOME,null);
  			}else if(orderRefund.getType()==VipTypeEnum.DEPOSIT_AMOUNT){
  	  			clientService.updateDepositAmount(orderRefund.getClientId(), orderRefund.getAmount().multiply(new BigDecimal("-1")));
  	  			consumeService.insertConsume(orderRefund.getClientId(),ConsumeSmallTypeEnum.REFUND_DEPOSIT_AMOUNT, MessageFormat.format(ConsumeMessageTemplate.MSG_REFUND_DEPOSIT, orderRefund.getAmount()),ConsumeLevelTypeEnum.WITHDRAWALS,null, null,ConsumeTypeEnum.OUTCOME,null);
  			}else if(orderRefund.getType()==VipTypeEnum.TALEND_ORDER){//达人订单
  	  			clientService.updateDepositAmount(orderRefund.getClientId(), orderRefund.getAmount());
  	  			consumeService.insertConsume(orderRefund.getClientId(),ConsumeSmallTypeEnum.REFUND_TALEND_ORDER, MessageFormat.format(ConsumeMessageTemplate.MSG_REFUND_TALEND_ORDER, orderRefund.getAmount()),ConsumeLevelTypeEnum.WITHDRAWALS,null, null,ConsumeTypeEnum.INCOME,null);
  	  			TalentOrder talentOrder=new TalentOrder();
  	  			talentOrder.setTradeNo(orderRefund.getTradeNo());
  	  			talentOrder.setStatus(OrderStatusEnum.FINISHED);
  	  			talentOrder.setAcceptStatus(OrderAcceptStatusEnum.FINISHED);
  	  			talentOrder.setPayStatus(PayStatusEnum.REFUND_PAYMENT);
  	  			talentOrderService.updateByTradeNo(talentOrder);
  			}
  		}
		Preconditions.checkNotNull(orderRefund, "entity in updating should not be NULL");
		orderRefund.setUpdateTime(OffsetDateTime.now());
		mapper.update(orderRefund);
		 
		return Boolean.TRUE;
	}


}
